package com.zlyx.easy.core.map;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;

import com.zlyx.easy.core.utils.JsonUtils;
import com.zlyx.easy.core.utils.StringUtils;

/**
 * @Auth 赵光
 * @Describle 数据Map
 */
public class DataMap implements Serializable {

	private static final long serialVersionUID = 1L;

	public static final String DEFAULT_REGEX = ":";

	private Map<String, Object> dataMap;

	private Map<String, Object> cacheMap;

	/**
	 * 多级key分割符
	 */
	private String regex;

	public DataMap() {
		this(DEFAULT_REGEX);
	}

	public DataMap(String regex) {
		this.dataMap = Maps.newMap();
		this.cacheMap = Maps.newMap();
		this.regex = regex;
		if (this.regex == null) {
			this.regex = DEFAULT_REGEX;
		}
	}

	public DataMap put(String key, Object value) {
		addValue(key, value);
		return this;
	}

	public DataMap putAll(Map<String, String> map) {
		dataMap.putAll(map);
		return this;
	}

	public boolean containsKey(String key) {
		return dataMap.containsKey(key);
	}

	public boolean withoutKey(String key) {
		return !containsKey(key);
	}

	public Set<String> keySet() {
		return dataMap.keySet();
	}

	/**
	 * 插入元素,例如:put("key1:key2:key3:key41", "123")
	 * 
	 * @param key
	 * @param values
	 * @return
	 */
	public DataMap addValue(String key, Object value) {
		if (key.contains(regex)) {
			putData(dataMap, key.split(regex), 0, value);
			cacheData(key, value);
		} else {
			dataMap.put(key, value);
		}
		return this;
	}

	/**
	 * 插入元素,例如: put("key", new Object[]{})
	 * 
	 * @param key
	 * @param values
	 * @return
	 */
	public DataMap addValue(String key, Object[] values) {
		addValue(key, Arrays.asList(values));
		return this;
	}

	/**
	 * 插入元素,例如: put("key", "123", "456")
	 * 
	 * @param key
	 * @param values
	 * @return
	 */
	public DataMap addValue(String key, String... values) {
		if (values.length > 1) {
			addValue(key, Arrays.asList(values));
		} else {
			addValue(key, values[0]);
		}
		return this;
	}

	/**
	 * 缓存多级key,提高查询效率,空间换时间的做法(当key的分级大于3时，自动开启)
	 * 
	 * @param multiKey
	 * @param value
	 */
	private void cacheData(String multiKey, Object value) {
		if (multiKey.split(regex).length > 5) {
			if (cacheMap == null) {
				cacheMap = Maps.newMap();
			}
			cacheMap.put(multiKey, value);
		}
	}

	@SuppressWarnings("unchecked")
	private Map<String, Object> putData(Map<String, Object> dataMap, String[] keyElements, int i, Object value) {
		Map<String, Object> elementMap = (Map<String, Object>) dataMap.get(keyElements[i]);
		if (keyElements.length - 1 > i && StringUtils.isNotEmpty(keyElements[i])) {
			if (elementMap == null) {
				elementMap = Maps.newMap();
			}
			dataMap.put(keyElements[i], putData(elementMap, keyElements, i + 1, value));
		} else {
			dataMap.put(keyElements[i], value);
		}
		return dataMap;
	}

	/**
	 * 查询元素,例如:get("key1:key2:key3:key41")
	 * 
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T get(String key) {
		if (cacheMap.containsKey(key)) {
			return (T) cacheMap.get(key);
		}
		if (key.contains(regex)) {
			return (T) getData(dataMap, key.split(regex), 0);
		}
		return (T) dataMap.get(key);
	}

	@SuppressWarnings("unchecked")
	private Object getData(Map<String, Object> dataMap, String[] keyElements, int i) {
		if (keyElements.length - 1 > i && StringUtils.isNotEmpty(keyElements[i])) {
			return getData((Map<String, Object>) dataMap.get(keyElements[i]), keyElements, i + 1);
		}
		return dataMap.get(keyElements[i]);
	}

	/**
	 * 查询元素,例如:get("key1:key2:key3:key41")
	 * 
	 * @param key
	 * @return
	 */
	public Object remove(String key) {
		if (key.contains(regex)) {
			remove(dataMap, key.split(regex), 0);
		}
		return cacheMap.remove(key);
	}

	@SuppressWarnings("unchecked")
	private Object remove(Map<String, Object> dataMap, String[] keyElements, int i) {
		if (keyElements.length - 1 > i && StringUtils.isNotEmpty(keyElements[i])) {
			return remove((Map<String, Object>) dataMap.get(keyElements[i]), keyElements, i + 1);
		}
		return dataMap.remove(keyElements[i]);
	}

	@Override
	public String toString() {
		return toJson();
	}

	public Map<String, Object> getDataMap() {
		return dataMap;
	}

	public void setDataMap(Map<String, Object> dataMap) {
		this.dataMap = dataMap;
	}

	public String toJson() {
		return JsonUtils.toJson(dataMap);
	}

	public Map<String, Object> toMap() {
		return dataMap;
	}

	public static DataMap newMap() {
		return new DataMap();
	}

	public static DataMap newMap(String separator) {
		return new DataMap(separator);
	}

	public static DataMap newMap(String key, Object value) {
		return newMap().addValue(key, value);
	}

	public static <T> DataMap newMap(Map<String, T> params) {
		return newMap(params, DEFAULT_REGEX);
	}

	public static <T> DataMap newMap(Map<String, T> params, String separator) {
		DataMap dataMap = DataMap.newMap(separator);
		for (String paramName : params.keySet()) {
			dataMap.put(paramName, params.get(paramName));
		}
		return dataMap;
	}

}
